package com.himiotech.core.project.data.dao;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;

import javax.sql.DataSource;
import java.sql.Connection;
import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * 此类为快速包装的 jdbcTemplate，方便一些语句直接 jdbc 查询
 * 某些情况下直接使用jdbc sql 语句查询，可以继承此接口，或者直接注入使用即可
 * 完整的详情见<br/>  https://github.com/miyakowork/simple-spring-jdbc
 *
 * @author wuwenbin
 */
public interface HimioJdbc {

    /**
     * 获得当前数据源
     *
     * @return 数据源
     */
    DataSource getCurrentDataSource();

    /**
     * 获取当前 jdbcTemplate 对象
     *
     * @return JdbcTemplate
     */
    JdbcTemplate getJdbcTemplateObj();

    /**
     * 获取 NamedParameterJdbcTemplate 对象
     *
     * @return NamedParameterJdbcTemplate
     */
    NamedParameterJdbcTemplate getNamedParameterJdbcTemplateObj();


    /**
     * 获取当前连接对象
     *
     * @return Connection
     * @throws Exception Exception
     */
    Connection getConnection() throws Exception;


    /**
     * 根据所给语句以及map级的sql类型参数，生成key
     *
     * @param sql          sql语句
     * @param mapParameter map类型的参数
     * @return 插入影响的条数
     * @throws Exception 插入的异常信息
     */
    int insertMapAutoGenKeyReturnAffect(String sql, Map<String, Object> mapParameter) throws Exception;

    /**
     * 插入bean返回插入的影响条数，自动生成key
     *
     * @param sql           插入sql语句
     * @param beanParameter bean类型参数
     * @return 插入影响的条数
     * @throws Exception 插入之中发生的异常
     */
    int insertBeanAutoGenKeyReturnAffect(String sql, Object beanParameter) throws Exception;

    /**
     * 插入Map返回插入的主键
     *
     * @param sql          插入的语句
     * @param mapParameter map类型的参数，对应sql中的占位符
     * @return 自动生成的主键
     * @throws Exception 插入时发生的异常
     */
    long insertMapAutoGenKeyReturnKey(String sql, Map<String, Object> mapParameter) throws Exception;

    /**
     * 插入bean返回插入的主键
     *
     * @param sql           插入的语句
     * @param beanParameter bean对象类型的参数，对应sql中的占位符
     * @return 自动生成的主键
     * @throws Exception 插入时发生的异常
     */
    long insertBeanAutoGenKeyReturnKey(String sql, Object beanParameter) throws Exception;

    /**
     * 插入一条Map记录，返回插入的记录（含主键）
     *
     * @param insertSql    插入语句
     * @param mapParameter map参数
     * @param pkName       主键列明
     * @return 所有字段组装成的map对象
     * @throws Exception 插入时发生的异常
     */
    Map<String, Object> insertMapAutoGenKeyReturnMap(String insertSql, Map<String, Object> mapParameter, String pkName) throws Exception;


    /**
     * 插入一条Bean记录，返回Map对象，参数类型为冒号
     *
     * @param insertSql     插入语句
     * @param beanParameter object参数
     * @param pkName        主键列
     * @return 插入的完整对象待主键id
     * @throws Exception Exception
     */
    Map<String, Object> insertBeanAutoGenKeyReturnMap(String insertSql, Object beanParameter, String pkName) throws Exception;


    /**
     * 插入一条记录，参数为Map返回一个对应的实体类
     *
     * @param insertSql    插入语句
     * @param mapParameter map参数
     * @param clazz        泛型类型
     * @param pkName       主键列明
     * @param <T>          对象泛型
     * @return
     * @throws Exception Exception
     */
    <T> T insertMapAutoGenKeyReturnBean(String insertSql, Map<String, Object> mapParameter, Class<T> clazz, String pkName) throws Exception;


    /**
     * 插入一条bean记录，返回插入记录（含主键）
     *
     * @param insertSql    插入语句
     * @param beaParameter bean类型参数
     * @param clazz        对象匹配的class类型
     * @param pkName       主键列明
     * @param <T>          对象匹配的泛型类型
     * @return 插入的对象
     * @throws Exception 插入时发生的异常
     */
    <T> T insertBeanAutoGenKeyReturnBean(String insertSql, Object beaParameter, Class<T> clazz, String pkName) throws Exception;

    /**
     * 执行 insert、update、delete方法都可
     *
     * @param sql             执行的sql语句
     * @param arrayParameters sql语句中的问号？参数
     * @return 影响条数
     * @throws Exception 执行异常
     */
    int executeArray(final String sql, Object... arrayParameters) throws Exception;

    /**
     * 执行 insert、update、delete方法都可
     *
     * @param sql          执行的sql语句
     * @param mapParameter sql语句中的冒号：参数
     * @return 影响条数
     * @throws Exception 执行异常
     */
    int executeMap(final String sql, Map<String, Object> mapParameter) throws Exception;

    /**
     * 执行 insert、update、delete方法都可
     *
     * @param sql           执行的sql语句
     * @param beanParameter sql语句中的冒号：参数
     * @return 影响条数
     * @throws Exception 执行异常
     */
    int executeBean(final String sql, Object beanParameter) throws Exception;

    /**
     * 批量执行 insert、update、delete方法都可
     *
     * @param sql           执行的sql语句
     * @param mapParameters sql语句中的冒号参数
     * @return 影响条数
     * @throws Exception 执行异常
     */
    int[] executeBatchByArrayMaps(String sql, Map<String, Object>... mapParameters) throws Exception;

    /**
     * 执行 insert、update、delete方法都可
     *
     * @param sql            执行的sql语句
     * @param beanParameters sql语句中的冒号：参数
     * @return 影响条数
     * @throws Exception 执行异常
     */
    int[] executeBatchByArrayBeans(String sql, Object... beanParameters) throws Exception;

    /**
     * 批量执行 insert、update、delete方法都可
     *
     * @param sql           执行的sql语句
     * @param mapParameters sql语句中的冒号参数
     * @return 影响条数
     * @throws Exception 执行异常
     */
    int[] executeBatchByCollectionMaps(String sql, Collection<Map<String, Object>> mapParameters) throws Exception;

    /**
     * 执行 insert、update、delete方法都可
     *
     * @param sql            执行的sql语句
     * @param beanParameters sql语句中的冒号：参数
     * @return 影响条数
     * @throws Exception 执行异常
     */
    int[] executeBatchByCollectionBeans(String sql, Collection<?> beanParameters) throws Exception;

    /**
     * 查询数字类型的结果：如max、avg、count等
     * 如果需要指定返回类型，则可以使用{@link HimioJdbc#findNumberByArray(String, Class, Object...)}
     *
     * @param sql             查询语句：select count(1) from table where id > ?
     * @param arrayParameters 数组参数
     * @return 数字结果
     */
    Number queryNumberByArray(final String sql, Object... arrayParameters);

    /**
     * 查询数字类型的结果：如max、avg、count等
     *
     * @param sql             查询语句：select count(1) from table where id > ?
     * @param numberClass     数字类型
     * @param arrayParameters 数组参数
     * @return 数字结果
     */
    <T extends Number> T findNumberByArray(final String sql, Class<T> numberClass, Object... arrayParameters);

    /**
     * 查询数字类型的结果：如max、avg、count等
     * 如果需要指定返回类型，则可以使用{@link HimioJdbc#findNumberByMap(String, Class, Map)}
     *
     * @param sql          查询语句：select count(1) from table where id > :id
     * @param mapParameter map参数
     * @return 数字结果
     */
    Number queryNumberByMap(final String sql, Map<String, Object> mapParameter);

    /**
     * 查询数字类型的结果：如max、avg、count等
     *
     * @param sql          查询语句：select count(1) from table where id > :id
     * @param numberClass  数字类型
     * @param mapParameter map参数
     * @return 数字结果
     */
    <T extends Number> T findNumberByMap(final String sql, Class<T> numberClass, Map<String, Object> mapParameter);

    /**
     * 查询数字类型的结果：如max、avg、count等
     * 如果需要指定返回类型，则可以使用{@link HimioJdbc#findNumberByBean(String, Class, Object)}
     *
     * @param sql           查询语句：select count(1) from table where id > :id
     * @param beanParameter object参数
     * @return 数字结果
     */
    Number queryNumberByBean(final String sql, Object beanParameter);

    /**
     * 查询数字类型的结果：如max、avg、count等
     *
     * @param sql           查询语句：select count(1) from table where id > :id
     * @param numberClass   数字类型
     * @param beanParameter object参数
     * @return 数字结果
     */
    <T extends Number> T findNumberByBean(final String sql, Class<T> numberClass, Object beanParameter);

    /**
     * 查询一列单条数据（8种基本类型的）
     *
     * @param sql             查询sql
     * @param objClass        可以为String、基本类型的包装类型，出此两种情况其余都不可以
     * @param arrayParameters sql语句中的参数
     * @param <T>             泛型对象
     * @return 基本类型实体类对象
     */
    <T> T findPrimitiveByArray(final String sql, Class<T> objClass, Object... arrayParameters);

    /**
     * 查询一列单条数据
     *
     * @param sql          查询 sql
     * @param objClass     可以为String、基本类型的包装类型，出此两种情况其余都不可以
     * @param mapParameter sql 参数
     * @param <T>          返回类型泛型
     * @return 返回对象
     */
    <T> T findPrimitiveByMap(final String sql, Class<T> objClass, Map<String, Object> mapParameter);

    /**
     * 查询一列单条数据
     *
     * @param sql           查询 sql
     * @param objClass      可以为String、基本类型的包装类型，出此两种情况其余都不可以
     * @param beanParameter sql 参数
     * @param <T>           对象类型泛型
     * @return 返回对象
     */
    <T> T findPrimitiveByBean(final String sql, Class<T> objClass, Object beanParameter);

    /**
     * 查询 map 对象结果
     *
     * @param sql             查询 sql
     * @param arrayParameters sql 查询参数
     * @return {@link Map} 返回结果（map）
     */
    Map<String, Object> findMapByArray(final String sql, Object... arrayParameters);

    /**
     * 查询map对象结果
     *
     * @param sql          查询 sql
     * @param mapParameter 查询参数
     * @return {@link Map} 返回对象（map）
     */
    Map<String, Object> findMapByMap(final String sql, Map<String, Object> mapParameter);

    /**
     * 查找map 对象，参数为冒号形式的对象
     *
     * @param sql           查询 sql
     * @param beanParameter sql 查询参数
     * @return 结果对象（map 包装）
     */
    Map<String, Object> findMapByBean(final String sql, Object beanParameter);

    /**
     * 通过 sql 查询对象
     *
     * @param sql             查询 sql
     * @param clazz           返回类型
     * @param arrayParameters 查询参数（数组）
     * @param <T>             返回对象类型泛型
     * @return {@link T}
     */
    <T> T findBeanByArray(final String sql, Class<T> clazz, Object... arrayParameters);

    /**
     * 通过 map 条件参数查询
     *
     * @param sql          查询 sql
     * @param clazz        返回类型
     * @param mapParameter 查询参数（map）
     * @param <T>          返回对象类型泛型
     * @return {@link T}
     */
    <T> T findBeanByMap(final String sql, Class<T> clazz, Map<String, Object> mapParameter);


    /**
     * 通过bean条件参数查找bean
     *
     * @param sql           查询的sql语句
     * @param clazz         需要匹配的对象class
     * @param beanParameter sql中的参数
     * @return
     */
    <T> T findBeanByBean(final String sql, Class<T> clazz, Object beanParameter);

    /**
     * 查询一列单条数据
     *
     * @param sql
     * @param objClass        可以为String、基本类型的包装类型，出此两种情况其余都不可以
     * @param arrayParameters sql语句中的参数
     * @param <T>
     * @return
     */
    <T> List<T> findListPrimitiveByArray(final String sql, Class<T> objClass, Object... arrayParameters);

    /**
     * 查询一列单条数据
     *
     * @param sql
     * @param objClass     可以为String、基本类型的包装类型，出此两种情况其余都不可以
     * @param mapParameter
     * @param <T>
     * @return
     */
    <T> List<T> findListPrimitiveByMap(final String sql, Class<T> objClass, Map<String, Object> mapParameter);

    /**
     * 查询一列单条数据
     *
     * @param sql
     * @param objClass      可以为String、基本类型的包装类型，出此两种情况其余都不可以
     * @param beanParameter
     * @param <T>
     * @return
     */
    <T> List<T> findListPrimitiveByBean(final String sql, Class<T> objClass, Object beanParameter);

    /**
     * 查询集合数据
     *
     * @param sql             业务逻辑 sql
     * @param arrayParameters 参数
     * @return {@link List<Map>}
     */
    List<Map<String, Object>> findListMapByArray(final String sql, Object... arrayParameters);

    /**
     * 查询集合数据
     *
     * @param sql          业务逻辑 sql
     * @param mapParameter 参数
     * @return {@link List<Map>}
     */
    List<Map<String, Object>> findListMapByMap(final String sql, Map<String, Object> mapParameter);

    /**
     * 查询list集合，参数为冒号形式的对象
     *
     * @param sql
     * @param beanParameter
     * @return
     */
    List<Map<String, Object>> findListMapByBean(final String sql, Object beanParameter);

    /**
     * 查询集合数据
     *
     * @param <T>             返回对象类型泛型
     * @param sql             业务逻辑 sql
     * @param clazz           返回对象类型
     * @param arrayParameters 查询参数
     * @return {@link List<T>}
     */
    <T> List<T> findListBeanByArray(final String sql, Class<T> clazz, Object... arrayParameters);

    /**
     * 查询集合数据
     *
     * @param <T>          返回对象类型泛型
     * @param sql          业务逻辑 sql
     * @param clazz        返回对象类型
     * @param mapParameter 查询参数
     * @return {@link List<T>}
     */
    <T> List<T> findListBeanByMap(final String sql, Class<T> clazz, Map<String, Object> mapParameter);

    /**
     * 查询集合数据
     *
     * @param <T>           返回对象类型泛型
     * @param sql           业务逻辑 sql
     * @param clazz         返回对象类型
     * @param beanParameter 查询参数
     * @return {@link List<T>}
     */
    <T> List<T> findListBeanByBean(final String sql, Class<T> clazz, Object beanParameter);

    /**
     * 查询集合数据
     *
     * @param sql             业务逻辑 sql，不包含 limit
     * @param page            分页信息
     * @param arrayParameters 查询参数
     * @return {@link Page}
     */
    Page<Map<String, Object>> findPageListMapByArray(final String sql, Page<Map<String, Object>> page, Object... arrayParameters);

    /**
     * 查询分页数据
     *
     * @param sql          业务逻辑 sql，不包含 limit
     * @param page         分页信息
     * @param mapParameter 参数
     * @return {@link Page}
     */
    Page<Map<String, Object>> findPageListMapByMap(final String sql, Page<Map<String, Object>> page, Map<String, Object> mapParameter);

    /**
     * 查询分页数据
     *
     * @param sql             业务逻辑 sql，不包含 limit
     * @param clazz           返回对象类型
     * @param page            分页信息
     * @param arrayParameters sql 查询参数
     * @return {@link Page}
     */
    <T> Page<T> findPageListBeanByArray(final String sql, Class<T> clazz, Page<T> page, Object... arrayParameters);

    /**
     * 查询分页数据
     *
     * @param sql          业务逻辑 sql，不包含 limit
     * @param clazz        返回对象类型
     * @param page         分页信息
     * @param mapParameter 查询参数
     * @return {@link Page}
     */
    <T> Page<T> findPageListBeanByMap(final String sql, Class<T> clazz, Page<T> page, Map<String, Object> mapParameter);

    /**
     * 分页查询
     *
     * @param sql           业务逻辑 sql，不包含 limit 部分
     * @param clazz         返回对象实体类型
     * @param page          分页信息
     * @param beanParameter 查询参数
     * @return {@link Page}
     */
    <T> Page<T> findPageListBeanByBean(final String sql, Class<T> clazz, Page<T> page, Object beanParameter);
}
